package cn.faifai.framework.utils.fetcher.fileIdFetcher.impl;

import cn.faifai.framework.jna.faifaiKernel32;
import cn.faifai.framework.utils.fetcher.fileIdFetcher.FileIdFetcher;


import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;


public class WindowsFileIdFetcher implements FileIdFetcher {


    /**
     * 获取操作系统下的文件id
     * @param filePath
     * @return dwVolumeSerialNumber-nFileIndexHigh-nFileIndexLow
     */
    public String getFileId(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        if (!Files.exists(path)) {
            throw new IOException("File not found: " + filePath);
        }

        String normalizedPath = "\\\\?\\" + path.toAbsolutePath().normalize().toString();

        WinNT.HANDLE hFile = faifaiKernel32.INSTANCE.CreateFileA(
                normalizedPath,
                new WinDef.DWORD(WinNT.GENERIC_READ),
                new WinDef.DWORD(WinNT.FILE_SHARE_READ),
                null,
                new WinDef.DWORD(WinNT.OPEN_EXISTING),
                new WinDef.DWORD(WinNT.FILE_ATTRIBUTE_NORMAL),
                null
        );

        if (WinNT.INVALID_HANDLE_VALUE.equals(hFile)) {
            throw new IOException("Failed to open file. Error code: " + Native.getLastError());
        }

        try {
            faifaiKernel32.BY_HANDLE_FILE_INFORMATION fileInfo = new faifaiKernel32.BY_HANDLE_FILE_INFORMATION();
            if (!faifaiKernel32.INSTANCE.GetFileInformationByHandle(hFile, fileInfo)) {
                throw new IOException("GetFileInformationByHandle failed. Error code: " + Native.getLastError());
            }

//            long fileIndex = ((long) fileInfo.nFileIndexHigh << 32) | (fileInfo.nFileIndexLow & 0xFFFFFFFFL);
            return String.format("%d#%d#%d", fileInfo.dwVolumeSerialNumber, fileInfo.nFileIndexHigh, fileInfo.nFileIndexLow);
        } finally {
            faifaiKernel32.INSTANCE.CloseHandle(hFile);
        }
    }
}
